package n8_设计模式_保护性暂停;

import lombok.extern.slf4j.Slf4j;
import utils.DownLoader;

import java.io.IOException;
import java.util.List;

/**
 * ----------------------------------------------------------------------
 * |                                                                    |
 * |     保护性暂停，[A线程] 等待 [B线程] 的结果                            |
 * |                                                                    |
 * |=====================================================================
 * 注意： 与join() 的区别；join是 [A线程] 等待 [B线程] 的 结束 (join源代码中是用wait实现的)
 * @author fu
 * @date 2021-12-21 21:58
 * 概要：
 * XXXXX
 */
@Slf4j(topic = "c.T1")
public class T1_Guarded {

    // [t1线程]  等待  [t2线程] 的下载结果
    public static void main(String[] args) {

        final Guarded guarded = new Guarded();

        // 1. 等待结果
        new Thread(()->{
            log.debug("等待结果...");
            final List<String> list = (List<String>) guarded.get();

            log.debug("结果大小：{}", list.size());

        }, "t1").start();

        new Thread(()->{

            log.debug("下载begin...");
            try {
                final List<String> list = DownLoader.download();
                guarded.complete(list);
                log.debug("下载end...");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }, "t2").start();

    }

}
@Slf4j(topic = "c.G")
class Guarded{

    private Object response = null;

    // 获取
    public Object get(){

        synchronized (this){
            log.debug("-----------保护性暂停中1------------");
            while(response == null){
                log.debug("-----------没有值进行等待------------");

                try {
                    this.wait();
                    log.debug("-----------有值了结束等待OK------------");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return this.response;
    }

    // 产生结果
    public void complete(Object res){

        synchronized (this){

            this.response = res;
            this.notifyAll();
        }

    }

}
